#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdint.h>
#include <iostream>
#include <atomic>
#include <emmintrin.h> // 用于_mm_pause指令
#include <errno.h>
#include <string.h>

#include "l1_msg.h"

// 线程函数：写入共享数据
void* writer_thread(void* arg) {
  ThreadArgs* args = (ThreadArgs*)arg;
  SharedData* shm = args->shm;
  // 将当前线程绑定到指定的CPU核心
  // 为了实现最低延迟的线程间通信，应将读写线程绑定到同一物理核心的两个逻辑核心（超线程）
  // 这样它们可以共享L1缓存，减少跨核同步开销
  cpupin(args->cpu_id);

  // 写入数据到共享内存（会被加载到L1缓存）
  for (int i = 0; i < MSG_COUNT; i++) {
    shm->seq_id = i;
    shm->time_cycles = rdtscp();  // 使用CPU周期计数代替系统时间
    std::atomic_thread_fence(std::memory_order_release); // 内存屏障确保数据写入完成
    shm->flag.store(1, std::memory_order_release);  // 通知读取方数据就绪
    while (shm->flag.load(std::memory_order_acquire) == 1) {
      _mm_pause(); // 减少CPU功耗，提示处理器其他线程可以使用超线程资源
    }
  }
  return NULL;
}

int main(int argc, char** argv) {
  // 检查命令行参数数量
  if (argc < 2) {
    std::cerr << "Usage: " << argv[0] << " <writer_cpu_id>" << std::endl;
    std::cerr << "Example: " << argv[0] << " 8  # Binds thread to specific CPU core" << std::endl;
    return 1;
  }

  // 创建或打开一个命名共享内存对象
  // /cross_proc_shm 是共享内存的名字，O_CREAT表示如果不存在则创建
  int fd = shm_open("/cross_proc_shm", O_RDWR, 0666);
  if (fd == -1) {
    std::cerr << "shm_open (writer) failed: " << strerror(errno) << std::endl;
    std::cerr << "Make sure the reader process is running first" << std::endl;
    return 1;
  }

  // 设置共享内存大小为SharedData结构体的大小
  if (ftruncate(fd, sizeof(SharedData)) == -1) {
    std::cerr << "ftruncate (writer) failed: " << strerror(errno) << std::endl;
    close(fd);
    return 1;
  }

  // 将共享内存映射到当前进程地址空间
  // MAP_SHARED保证其他进程/线程可见修改
  SharedData* shm = (SharedData*)mmap(NULL, sizeof(SharedData),
                                      PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if (shm == MAP_FAILED) {
    std::cerr << "mmap (writer) failed: " << strerror(errno) << std::endl;
    close(fd);
    return 1;
  }

  // 验证映射的内存是否有效
  if (shm == nullptr) {
    std::cerr << "Failed to map shared memory" << std::endl;
    munmap(shm, sizeof(SharedData));
    close(fd);
    shm_unlink("/cross_proc_shm");
    return 1;
  }

  // 等待一小段时间，确保reader已经准备好
  usleep(100000); // 等待100毫秒

  // 创建线程参数，接收用户指定的CPU ID
  ThreadArgs writer_args = {shm, atoi(argv[1])};

  // 创建写线程
  pthread_t writer;
  if (pthread_create(&writer, NULL, writer_thread, &writer_args) != 0) {
    std::cerr << "Failed to create writer thread" << std::endl;
    munmap(shm, sizeof(SharedData));
    close(fd);
    shm_unlink("/cross_proc_shm");
    return 1;
  }

  // 等待写线程完成
  pthread_join(writer, NULL);

  // 清理资源
  munmap(shm, sizeof(SharedData));  // 解除内存映射
  close(fd);
  // 注意：不要在这里删除共享内存对象，因为读取进程可能还在使用它
  // shm_unlink("/cross_proc_shm"); 

  return 0;
}